/*
 * Copyright (c) 2015. For Intelligent Group.
 */

package com.intelligent.ispc.common.web;

import com.intelligent.ispc.common.persistence.SearchFilter;
import com.intelligent.ispc.common.utils.Collections3;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;

import javax.servlet.ServletRequest;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

/**
 * Http and Servlet tools.
 * <p>
 * Created by Peter.Li on 2015/10/9.
 */
public class Servlets {

    /**
     * Get the Request Parameters with prefix, to build the search param with the operator provided.
     * <p>
     * return the Parameter with this format: key:EQ_loginName, value:XXX
     */
    public static Map<String, Object> getParametersStartingWith(ServletRequest request, String prefix, Map<String, SearchFilter.Operator> map) {
        Map<String, Object> params = new TreeMap<String, Object>();
        Enumeration paramNames = request.getParameterNames();

        while ((paramNames != null) && paramNames.hasMoreElements()) {
            String paramName = (String) paramNames.nextElement();
            if ("".equals(prefix) || paramName.startsWith(prefix)) {
                String unprefixed = paramName.substring(prefix.length());
                String[] values = request.getParameterValues(paramName);

                if ((values == null) || (values.length == 0)) {
                    // Do nothing, no values found at all.
                } else if (values.length > 1) {
                    params.put(map.get(unprefixed).toString() + "_" + unprefixed, values);
                } else {
                    if (map.containsKey(unprefixed)) {
                        params.put(map.get(unprefixed).toString() + "_" + unprefixed, values[0]);
                    }
                }
            }
        }
        return params;
    }

    /**
     * Get the parameters which holds the same prefix, copy from spring WebUtils.
     * <p>
     * Return the parameters with no prefix.
     */
    public static Map<String, Object> getParametersStartingWith(ServletRequest request, String prefix) {
        Validate.notNull(request, "Request must not be null");
        Enumeration paramNames = request.getParameterNames();
        Map<String, Object> params = new TreeMap<String, Object>();
        if (prefix == null) {
            prefix = "";
        }
        while ((paramNames != null) && paramNames.hasMoreElements()) {
            String paramName = (String) paramNames.nextElement();
            if ("".equals(prefix) || paramName.startsWith(prefix)) {
                String unprefixed = paramName.substring(prefix.length());
                String[] values = request.getParameterValues(paramName);
                if ((values == null) || (values.length == 0)) {
                    // Do nothing, no values found at all.
                } else if (values.length > 1) {
                    params.put(unprefixed, values);
                } else {
                    if (StringUtils.isNotBlank(values[0])) {
                        params.put(unprefixed, values[0]);
                    }
                }
            }
        }
        return params;
    }

    /**
     * Build Parameters, put the prefix to the parameter name.
     *
     * @see #getParametersStartingWith
     */
    public static String encodeParameterStringWithPrefix(Map<String, Object> params, String prefix) {
        if (Collections3.isEmpty(params)) {
            return "";
        }

        if (prefix == null) {
            prefix = "";
        }

        StringBuilder queryStringBuilder = new StringBuilder();
        Iterator<Entry<String, Object>> it = params.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, Object> entry = it.next();
            queryStringBuilder.append(prefix).append(entry.getKey()).append('=').append(entry.getValue());
            if (it.hasNext()) {
                queryStringBuilder.append('&');
            }
        }
        return queryStringBuilder.toString();
    }
}
